﻿using System;
using System.Threading.Tasks;

namespace VeryGoodSync
{
    /// <summary>
    /// 延时指定时长之后再执行代码，可取消，类似于javascript中的SetTimeout, 待执行的方法需要自行处理异常
    /// </summary>
    sealed class SetTimeout
    {
        /// <summary>
        /// 创建一个新的延时器
        /// </summary>
        /// <param name="delay">延时时长，单位毫秒</param>
        /// <param name="action">延时到期之后需要执行的代码</param>
        /// <returns></returns>
        public static SetTimeout New(int delay, Action action)
        {
            return new SetTimeout(delay, action);
        }

        private readonly object _cancelLock = new object();
        private readonly Action _action;
        private readonly int _delay;

        private bool _isCanceled;

        /// <summary>
        /// 创建一个新的延时器
        /// </summary>
        /// <param name="delay">延时时长，单位毫秒</param>
        /// <param name="action">延时到期之后需要执行的代码</param>
        public SetTimeout(int delay, Action action)
        {
            if (delay <= 0) throw new ArgumentException($"参数{nameof(delay)}必须大于0");
            _delay = delay;
            _action = action ?? throw new ArgumentNullException(nameof(action));
            Start();
        }

        /// <summary>
        /// 启动延时器
        /// </summary>
        async void Start()
        {
            await Task.Delay(_delay);
            lock (_cancelLock)
            {
                if (_isCanceled) return;
            }

            try
            {
                _action();
            }
            catch (Exception ex)
            {
                Ui.TraceError("执行任务出错", ex);
            }
        }

        /// <summary>
        /// 取消延时器
        /// </summary>
        public void Cancel()
        {
            lock (_cancelLock)
            {
                _isCanceled = true;
            }
        }
    }
}
